Fix a stack overflow in format (CVE-2007-6109).
authorRob Browning <rlb@defaultvalue.org>
Mon, 25 Feb 2008 05:54:51 +0000 (21:54 -0800)
committerRob Browning <rlb@defaultvalue.org>
Mon, 25 Feb 2008 05:54:51 +0000 (21:54 -0800)
debian/changelog
debian/patches/fix-format-overflow-cve-2007-6109.diff [new file with mode: 0644]
debian/patches/series

index 1f08057181568328f2d533f154a658b142cd64da..b6a1700b15941f84787a02f6fae0b4107378fefc 100644 (file)
@@ -8,7 +8,15 @@ emacs22 (22.1+1-3) unstable; urgency=low
   * Support has been added for GNU/kFreeBSD.  Thanks to Petr Salinger
     <Petr.Salinger@seznam.cz> (closes: #451178)
 
- -- Rob Browning <rlb@defaultvalue.org>  Sun, 24 Feb 2008 21:45:59 -0800
+  * Incorporate a patch to fix a a stack-based buffer overflow in the
+    format function which can occur when dealing with high precision
+    values.  The overflow could lead to arbitrary code execution
+    (CVE-2007-6109).  Thanks to Nico Golde <nion@debian.org> for the
+    22.1+1-2.2 and 22.1+1-2.3 NMUs.  The patch fixes both the CVE
+    (#455432) and a bug introduced by an incomplete initial patch
+    (#456235).
+
+ -- Rob Browning <rlb@defaultvalue.org>  Sun, 24 Feb 2008 21:52:24 -0800
 
 emacs22 (22.1+1-2) unstable; urgency=low
 
diff --git a/debian/patches/fix-format-overflow-cve-2007-6109.diff b/debian/patches/fix-format-overflow-cve-2007-6109.diff
new file mode 100644 (file)
index 0000000..2893e8a
--- /dev/null
@@ -0,0 +1,91 @@
+* A stack overflow in the format function has been fixed.
+  Patch: fix-format-overflow-cve-2007-6109.diff
+  Provided-by: Nico Golde <nion@debian.org>
+  Date: Mon, 10 Dec 2007 02:54:44 +0100
+  Added-by: Rob Browning <rlb@defaultvalue.org>
+  Status: incorporated upstream
+
+  A stack-based buffer overflow in the format function has been fixed,
+  one that could lead to arbitrary code execution.  The overflow could
+  happen when dealing with high precision values (CVE-2007-6109).
+
+Index: sid/src/editfns.c
+===================================================================
+--- sid.orig/src/editfns.c
++++ sid/src/editfns.c
+@@ -3543,8 +3543,10 @@
+             precision[n+1] = 10 * precision[n+1] + *format - '0';
+         }
+-      if (format - this_format_start + 1 > longest_format)
+-        longest_format = format - this_format_start + 1;
++      /* Extra +1 for 'l' that we may need to insert into the
++         format.  */
++      if (format - this_format_start + 2 > longest_format)
++        longest_format = format - this_format_start + 2;
+       if (format == end)
+         error ("Format string ends in middle of format specifier");
+@@ -3605,7 +3607,7 @@
+                 && *format != 'i' && *format != 'X' && *format != 'c')
+               error ("Invalid format operation %%%c", *format);
+-          thissize = 30;
++          thissize = 30 + (precision[n] > 0 ? precision[n] : 0);
+           if (*format == 'c')
+             {
+               if (! SINGLE_BYTE_CHAR_P (XINT (args[n]))
+@@ -3803,23 +3805,39 @@
+                    format - this_format_start);
+             this_format[format - this_format_start] = 0;
+-            if (INTEGERP (args[n]))
++            if (format[-1] == 'e' || format[-1] == 'f' || format[-1] == 'g')
++              sprintf (p, this_format, XFLOAT_DATA (args[n]));
++            else
+               {
+-                if (format[-1] == 'd')
+-                  sprintf (p, this_format, XINT (args[n]));
+-                /* Don't sign-extend for octal or hex printing.  */
++                if (sizeof (EMACS_INT) > sizeof (int) && format[-1] != 'c')
++                  {
++                    /* Insert 'l' before format spec.  */
++                    this_format[format - this_format_start]
++                      = this_format[format - this_format_start - 1];
++                    this_format[format - this_format_start - 1] = 'l';
++                    this_format[format - this_format_start + 1] = 0;
++                  }
++
++                if (INTEGERP (args[n]))
++                  {
++                    if (format[-1] == 'c')
++                      sprintf (p, this_format, (int) XINT (args[n]));
++                    else if (format[-1] == 'd')
++                      sprintf (p, this_format, XINT (args[n]));
++                    /* Don't sign-extend for octal or hex printing.  */
++                    else
++                      sprintf (p, this_format, XUINT (args[n]));
++                  }
++                else if (format[-1] == 'c')
++                  sprintf (p, this_format, (int) XFLOAT_DATA (args[n]));
++                else if (format[-1] == 'd')
++                  /* Maybe we should use "%1.0f" instead so it also works
++                     for values larger than MAXINT.  */
++                  sprintf (p, this_format, (EMACS_INT) XFLOAT_DATA (args[n]));
+                 else
+-                  sprintf (p, this_format, XUINT (args[n]));
++                  /* Don't sign-extend for octal or hex printing.  */
++                  sprintf (p, this_format, (EMACS_UINT) XFLOAT_DATA (args[n]));
+               }
+-            else if (format[-1] == 'e' || format[-1] == 'f' || format[-1] == 'g')
+-              sprintf (p, this_format, XFLOAT_DATA (args[n]));
+-            else if (format[-1] == 'd')
+-              /* Maybe we should use "%1.0f" instead so it also works
+-                 for values larger than MAXINT.  */
+-              sprintf (p, this_format, (EMACS_INT) XFLOAT_DATA (args[n]));
+-            else
+-              /* Don't sign-extend for octal or hex printing.  */
+-              sprintf (p, this_format, (EMACS_UINT) XFLOAT_DATA (args[n]));
+             if (p > buf
+                 && multibyte
index 782493ca4c5f3b181964ad0816076ea6e5d14cbf..f7397b26a27f665e3a91ef057ac7921f00e1334f 100644 (file)
@@ -12,4 +12,5 @@ require-movemail-use-liblockfile.diff
 avoid-fakemail-mail-loss.diff
 version-mention-debian.diff
 support-gnu-kfreebsd.diff
+fix-format-overflow-cve-2007-6109.diff
 autofiles.diff